#include "net/net.h" 
#include "pack/pack.h" 
#include "net/flatbuffer.h"

#include <ctime>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;

class HelloWorldPacket : public pack::IPacket {
	public:
		std::string str;	

	public:
		HelloWorldPacket() {
			str = "Hello, I am CIW_MATRIX.";
		}

		~HelloWorldPacket() {

		}

		uint32_t GetUri() {
			return 1;
		}

		bool Pack(pack::Writer& writer) {
			writer<<str;
			return true;
		}

		bool UnPack(pack::Reader& reader) {
			return reader>>str;
		}

        std::string Dump() {

        }
};

class SocketHandler : public net::ISocketHandler {
	public:
		virtual void OnRead(net::ISocket* socket) {
            char buf[1000];
            socket->GetInBuffer()->Read(buf, 100);
            cout<<buf<<endl;

			socket->Send("Client!!", 9);
			/*HelloWorldPacket packet;
			pack::Request in_request(socket->GetInBuffer());
			pack::Request out_request(socket->GetOutBuffer());

            while (in_request.GetPack()) {
                if (in_request.UnPack(&packet)) {
				    cout<<packet.str<<endl;
                }
            }
			uint32_t n = rand() % 100;
			packet.str = "";
			for(int i = 0; i < n; i++) {
				packet.str += "Client";
			}

			out_request.Pack(&packet);
			socket->Send("", 0);

            cout<<"OnRead"<<endl;*/
		}

		virtual void OnWrite(net::ISocket* socket) {

		}

		virtual void OnClose(net::ISocket* socket) {
            cout<<"OnClose"<<endl;
		}

		virtual void OnConnected(net::ISocket* socket) {
			HelloWorldPacket packet;
			pack::Request request(socket->GetOutBuffer());

			request.Pack(&packet);
			socket->Send("", 0);

            cout<<"OnConnected"<<endl;
		}

		virtual void OnError(net::ISocket* socket, uint32_t error) {
            cout<<"OnError"<<endl;
		}
};

int main() {
	SocketHandler handler;
	net::NetAddress address("127.0.0.1", 9999);
	net::IReactor* reactor = net::GetReactor();
	net::ISocket* socket = net::GetSocket();

	srand(time(NULL));

	socket->Connect(address);
	socket->SetHandler(&handler);

	reactor->Dispatch();
	return 0;
}
